#pragma once

namespace Melting
{

namespace Parallel
{

	//--------------------------------------------------------------------------------------------------------------------	
#ifdef WIN32
	typedef CONDITION_VARIABLE 		ConditionVariableHandle;

#else // pthread
	typedef pthread_cond_t 			ConditionVariableHandle;

#endif

	//--------------------------------------------------------------------------------------------------------------------
	class ConditionVariable
	{
	public:

		inline ConditionVariable	( void );
		inline ~ConditionVariable	( void );

		/// Signal and wake 1 thread 
		inline void		SignalOne	( void );
		/// Signal and wake all threads
		inline void		SignalAll	( void );
		/// Sleep until its waken
		inline void		Wait		( Mutex& _rLocker );

	private:

		ConditionVariableHandle	mHandle;
	};


#ifdef WIN32

	//----------------------------------------------------------------
	//----------------------------------------------------------------
	ConditionVariable::ConditionVariable( void )
	{
		InitializeConditionVariable( & mHandle );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	ConditionVariable::~ConditionVariable( void )
	{
		// NOTHING
	}

	//----------------------------------------------------------------
	//----------------------------------------------------------------
	void ConditionVariable::SignalOne( void )
	{
		WakeConditionVariable( & mHandle );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	void ConditionVariable::SignalAll( void )
	{
		WakeAllConditionVariable( & mHandle );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	void ConditionVariable::Wait( Mutex& _rLocker )
	{
		// for critical sections... 
		SleepConditionVariableCS( & mHandle, & _rLocker.mHandle, INFINITE );

		//// for slim read write locks... 
		//SleepConditionVariableSRW( & mHandle, & _rLocker, INFINITE );
	} 


#else// PTHREAD

	//----------------------------------------------------------------
	//----------------------------------------------------------------
	ConditionVariable::ConditionVariable( void )
	{	
		INT32 iResult = pthread_cond_init( & mHandle );
		MB_ASSERT( 0 == iResult );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	ConditionVariable::~ConditionVariable( void )
	{		
		INT32 iResult = pthread_cond_destroy( & mHandle );
		MB_ASSERT( 0 == iResult );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	void ConditionVariable::SignalOne( void )
	{
		INT32 iResult = pthread_cond_signal( & mHandle );
		MB_ASSERT( 0 == iResult );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	void ConditionVariable::SignalAll( void )
	{
		INT32 iResult = pthread_cond_broadcast( & mHandle );
		MB_ASSERT( 0 == iResult );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	bool ConditionVariable::Wait( Locker& _rLocker )
	{
		INT32 iResult =  pthread_cond_wait( & mHandle, & _rLocker.mHandle );
		MB_ASSERT( 0 == iResult );
	} 

#endif 
}
}// namespace Melting